var SBimsc = {alpha:'0123456789abcdef', __debug:false, socks:null, hooks:{}};
SBimsc.sethooks = function(skey, cb) {//定义事件回到机制
    SBimsc.hooks[skey] = cb;
};
SBimsc.debug = function() {
    if (!SBimsc.__debug) {
        return;
    }
    for(var i = 0; i < arguments.length; i++) {
        console.log(arguments[i]);
    }
};
SBimsc.coString = function (data) {
    (!data) && (data = 0);
    if (data.constructor !== String) {
        return (new Number(data)).toString();
    }
    return data;
};
SBimsc.compress = function (str) {
    try {
        let deflate= new pako.Deflate();
        let datbuf = new ByteBuffer(str.length * 3);
        let nsize  = datbuf.writeString(str);
        datbuf     = datbuf.slice(0, nsize);
        deflate.push(datbuf.raw, true);
        if (deflate.err) {//数据解压出来失败的业务逻辑
            throw { code: 503, msg: "data compress error:" + deflate.err + "!" };
        }
        datbuf = new ByteBuffer(deflate.result);
        return nsize + '$' + Base64.fromUint8Array(datbuf.raw)
    } catch (err) {
        throw { code: 503, msg: "data compress error:" + err.toString() + "!" };
    }
};
SBimsc.sethooks("error", SBimsc.debug);
SBimsc.sethooks("cbchat", SBimsc.debug);
SBimsc.sethooks("onmessage", SBimsc.debug);
SBimsc.websocks = function(uri, user, chnid, vkey) {
    var self    = this;
    (SBimsc.socks) && SBimsc.socks.close();
    self._uri   = uri;
    self._vkey 	= vkey;
    self._user  = user;//{userid,nick,avatar,gender}
    self._uin   = SBimsc.coString(user.userid);
    self._chnid = SBimsc.coString(chnid);
    self._signin= false;
    self._enter = false;
    self._touser= null;
    self._mqueue= {};
    if (!window.JSON) {
        SBimsc.hooks.error("your broswer could not support JSON!");
        return;
    };
    if (!!window.WebSocket) {
        SBimsc.socks = new WebSocket(uri);
    } else if (!!window.MozWebSocket) {
        SBimsc.socks = new MozWebSocket(uri);
    } else {
        SBimsc.hooks.error("your broswer could not support websocket!");
        return;
    };
    SBimsc.socks.onmessage = function(evt) {
        self.onmessage(evt);
    };
    SBimsc.socks.onclose = function(evt) {
        self.onclose(evt);
    };
    SBimsc.socks.onopen = function(evt) {
        self.onopen(evt);
    };
};

//执行业务对象实例
SBimsc.websocks.prototype = {
    constructor:SBimsc.websocks,
    uuid: function() {
        var i, astr = [];
        for (i = 0; i < 36; i++) {
            astr[i] = SBimsc.alpha.substr(Math.floor(Math.random() * 0x10), 1);
        }
        astr[14] = "4";
        astr[19] = SBimsc.alpha.substr((astr[19] & 0x3) | 0x8, 1);
        astr[8]  = astr[13] = astr[18] = astr[23] = "-";
        return astr.join("");
    },
    dologin: function() {
        var self  = this;
        var seqno = self.uuid();
        var jspack= {userid:self._uin, vkey:self._vkey};
        jspack  = JSON.stringify(jspack);
        self.sendPacket(1, seqno, jspack);
    },
    doenter: function(chnid, optype) {
        var self= this;
        if (!self._signin || chnid < 1) {
            return false;
        }
        self._chlid= SBimsc.coString(chnid);
        var seqno  = self.uuid();
        var jspack = {'chnid':self._chlid, 'optype': (optype)? 1:0};
        jspack     = JSON.stringify(jspack);
        self.sendPacket(2, seqno, jspack);
    },
    dochan: function(chnid, message, type, targetid) {//频道处理逻辑
        var self = this;
        chnid = SBimsc.coString(chnid);
        if (!message || !self._signin) {
            return false;
        }
        var type   = (type)? parseInt(type):0;
        var targetid = (new Number(targetid)).toString();
        var seqno  = self.uuid();//记录uuid唯一标识
        var packet = {userid:self._uin, user:self._user, messages:message,
            touserid:chnid, touser:null, targetid:targetid, type:type};
        var jspack = JSON.stringify(packet);
        self._mqueue[seqno] = packet;
        self.sendPacket(4, seqno, jspack);
    },
    setTouser: function (user) {
        var self = this;
        self.touser = user;
    },
    douser: function(message, type, targetid) {//私聊处理逻辑
        var self = this;
        var touserid = SBimsc.coString((this.touser)? this.touser.userid:0);
        if (!msg || !self._signin || touserid < 1) {
            return false;
        }
        var type = (type)? parseInt(type):0;
        var targetid = SBimsc.coString(targetid);
        var seqno  = self.uuid();//记录uuid唯一标识
        var packet = {userid:self._uin, user:self._user, messages:message,
            touserid:touserid, touser:this.touser, targetid:targetid, type:type};
        var jspack = JSON.stringify(packet);
        self._mqueue[seqno] = packet;
        self.sendPacket(3, seqno, jspack);
    },
    cbproc: function(data) {//处理消息业务逻辑
        var self = this;
        //设置登录信息回调
        if(data.opcmd == 1) {//登录成功的回调
            if(data.code == 0) {
                self._signin = true;
                (self._chnid > 0) && self.doenter(self._chnid, 1);
            } else {
                self._signin = false;
                self._enter  = false;
            }
        } else if (data.opcmd == 2 && data.code == 0) {
            self._enter = true;
        } else if (data.opcmd == 3 || data.opcmd == 4) {//发送消息回调
            if(data.code == 0 && !!SBimsc.hooks.cbchat && self._mqueue[data.seqno]) {
                SBimsc.hooks.cbchat(data, self._mqueue[data.seqno]);
                delete self._mqueue[data.seqno];
            }
        }
    },
    onopen: function(evt) {
        var self= this;
        SBimsc.debug("websockets connected.");
        self.dologin();
    },
    onclose: function(evt) {
        var self = this;
        self._signin = false;
        self._enter  = false;
        SBimsc.debug("websockets closed.");
    },
    onmessage: function(evt) {
        var self = this;
        try {
            var json = evt.data;
            json = JSON.parse(json);
            if(json) {
                self.cbproc(json);
                SBimsc.hooks.onmessage(json);
            }
            SBimsc.debug("websockets onmessage.", evt);
        } catch(err) {
            SBimsc.debug(err);
        }
    },
    sendPacket: function(apcode, seqno, json) {
        var data  = {'opcmd':apcode, 'seqno':seqno, 'packet':json};
        data = JSON.stringify(data);
        data = SBimsc.compress(data);
        if (SBimsc.socks) {
            SBimsc.socks.send(data);
        };
    }
};